package com.mmx.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.mmx.constant.NodeConstant;
import com.mmx.domain.bean.FlowData;
import com.mmx.domain.bean.NextNodeData;
import com.mmx.domain.bean.NodeData;
import com.mmx.service.FlowDataService;
import com.mmx.task.AbstractTaskNode;
import com.mmx.util.SpringUtil;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @desc: 流程数据操作实现类
 * @author: liushuai
 * @date: 2023/1/31 10:52
 */
@Service
public class FlowDataServiceImpl implements FlowDataService {
    @Override
    public FlowData checkFlowData(String flowData) {
        if (!JSONUtil.isTypeJSONObject(flowData)) {
            throw new IllegalArgumentException("The flowData parameter is not a JSONObject");
        }
        JSONObject jsonObject = new JSONObject(flowData);
        FlowData flowObj = Optional.ofNullable(JSONUtil.toBean(jsonObject, FlowData.class)).orElse(new FlowData());
        if (StrUtil.isEmpty(flowObj.getDefinitionKey())) {
            throw new NullPointerException("definitionKey cannot be empty");
        }
        //流程节点
        List<NodeData> nodes = flowObj.getNodes();
        if (CollectionUtil.isEmpty(nodes)) {
            throw new RuntimeException("nodes cannot be empty ");
        }
        NodeData startNode = null;
        NodeData endNode = null;
        for (NodeData nodeData : nodes) {
            if (StrUtil.isEmpty(nodeData.getId())) {
                throw new NullPointerException("node id cannot be empty");
            }
            String type = nodeData.getType();
            if (StrUtil.isEmpty(type)) {
                throw new NullPointerException("node type cannot be empty");
            }
            if (NodeConstant.START.equals(type)) {
                startNode = nodeData;
            }
            if (NodeConstant.END.equals(type)) {
                endNode = nodeData;
            }
        }
        if (startNode == null) {
            throw new NullPointerException("start node cannot be empty");
        }
        if (endNode == null) {
            throw new NullPointerException("end node cannot be empty");
        }
        return flowObj;
    }

    @Override
    public NextNodeData taskFlow(String flowData, String nodeId, Map<String, Object> variables) {
        JSONObject jsonObject = new JSONObject(flowData);
        FlowData flowObj = JSONUtil.toBean(jsonObject, FlowData.class);
        List<NodeData> nodes = flowObj.getNodes();
        NodeData startNode = null;
        NodeData currentNode = null;
        for (NodeData node : nodes) {
            if (NodeConstant.START.equals(node.getType())) {
                startNode = node;
            }
            if (node.getId().equals(nodeId)) {
                currentNode = node;
            }
        }
        if (nodeId == null) {
            currentNode = startNode;
        }
        AbstractTaskNode taskNode = SpringUtil.getBean(currentNode.getType());
        List<NodeData> executeNodes = taskNode.execute(flowObj, currentNode, variables);
        return NextNodeData.builder()
                .startNodeId(startNode.getId())
                .nodeDataList(executeNodes)
                .build();
    }


}
